/**
 * Copyright (c) 2011 Nokia Corporation.
 */

// Own header
#include "filemodel.h"

// Qt includes
#include <QFileInfo>

// Backup2Go includes
#include "trace.h"


/*!
  \class FileModel
  \brief A model for handling the content of a single directory.
*/


/*!
  Constructor.
*/
FileModel::FileModel(QObject *parent /* = 0 */)
    : m_foldersOnly(true)
{
    QHash<int, QByteArray> roles;
    roles[TypeRole] = "type";
    roles[NameRole] = "name";
    roles[SizeRole] = "fileSize";
    roles[StatusRole] = "status";
    setRoleNames(roles);
}


/*!
  Destructor.
*/
FileModel::~FileModel()
{
}


/*!
  From QAbstractListModel.
*/
QVariant FileModel::data(const QModelIndex &index,
                         int role /* = Qt::DisplayRole */) const
{
    const int itemIndex(index.row());

    if (!index.isValid() || itemIndex >= m_files.count()) {
        // Invalid index!
        DEBUG_INFO("Invalid index:" << itemIndex);
        return QVariant();
    }

    QVariant value = QVariant();

    switch (role) {
        case TypeRole: {
            if (m_files[itemIndex].isDir()) {
                value = QVariant::fromValue((int)Directory);
            }
            else {
                value = QVariant::fromValue((int)File);
            }

            break;
        }
        case NameRole: {
            value = QVariant::fromValue(m_files[itemIndex].fileName());
            break;
        }
        case SizeRole: {
            value = QVariant::fromValue(m_files[itemIndex].size());
            break;
        }
        case StatusRole: {
            if (m_fileStatuses.contains(itemIndex)) {
                value = QVariant::fromValue((int)m_fileStatuses[itemIndex]);
            }
            else {
                value = QVariant::fromValue((int)None);
            }

            break;
        }
    } // switch (role)

    return value;
}


/*!
  From QAbstractListModel.
*/
int FileModel::rowCount(const QModelIndex &parent /* = QModelIndex() */) const
{
    Q_UNUSED(parent);
    return m_files.count();
}


/*!
  From QAbstractListModel.
*/
void FileModel::removeRow(int row, const QModelIndex &parent)
{
    if (0 > row && row > m_files.count() - 1) {
        // Invalid row!
        return;
    }

    beginRemoveRows(QModelIndex(), row, row);

    m_files.removeAt(row);

    if (m_fileStatuses.contains(row)) {
        m_fileStatuses.remove(row);
    }

    endRemoveRows();
}


/*!
  Appends \a fileInfo with the \a status into the model.
*/
void FileModel::appendFile(QFileInfo &fileInfo, Status status /* = None */)
{
    DEBUG_INFO("Appending: " << fileInfo.fileName());

    const int count(m_files.count());
    beginInsertRows(QModelIndex(), count, count);
    m_files.append(fileInfo);
    m_fileStatuses.insert(count, status);
    endInsertRows();
}


/*!
  For convenience.
  Appends the meta data of \a file into the model.
*/
void FileModel::appendFile(QFile &file, Status status /* = None */)
{
    QFileInfo fileInfo(file);
    appendFile(fileInfo, status);
}


/*!
  Sets \a fileInfoList as the model content but may discard some items.
*/
void FileModel::setFiles(QFileInfoList fileInfoList)
{
    DEBUG_INFO("The list to set contains" <<
               fileInfoList.count() << "items.");

    if (m_files.count()) {
        clear();
    }

    QFileInfo fileInfo;

    foreach (fileInfo, fileInfoList) {
        if (fileInfo.isDir() &&
            (!fileInfo.fileName().compare(".") ||
             !fileInfo.fileName().compare(".."))) {
            // Filter paths "." and ".." out.
            continue;
        }

        if (m_foldersOnly && !fileInfo.isDir()) {
            // Accept only folders.
            continue;
        }

        appendFile(fileInfo);
    }
}


/*!
  Returns the model content.
*/
QFileInfoList &FileModel::files()
{
    return m_files;
}


/*!
  Sets the file info from \a index into \a fileInfo.
  Returns true if success, false if \a index is invalid.
*/
bool FileModel::getFileInfo(int index, QFileInfo &fileInfo) const
{
    if (index < 0 || index >= m_files.count()) {
        // Invalid index!
        DEBUG_INFO("Invalid index (" << index <<
                   "), the model item count is" << m_files.count() << "!");
        return false;
    }

    fileInfo = m_files[index];
    return true;
}


/*!
  Sets \a status for the file with \a index.
*/
void FileModel::setFileStatus(int index, Status status)
{
    DEBUG_INFO("[" << index << "] => " << (int)status);

    if (index >= 0 && m_files.count() > index) {
        m_fileStatuses[index] = status;
        QModelIndex modelIndex = createIndex(index, 0);
        emit dataChanged(modelIndex, modelIndex);
    }
#ifdef DEBUG
    else {
        DEBUG_INFO("Invalid index!");
    }
#endif
}


/*!
  Sets \a statuses as the file statuses.
*/
void FileModel::setFileStatuses(QMap<int, Status> &statuses)
{
#ifdef DEBUG
    if (statuses.count()) {
        DEBUG_INFO("Set statuses:");

        foreach (int key, statuses.keys()) {
            DEBUG_INFO("[" << key << "] =>" << (int)statuses[key]);
        }
    }
    else {
        DEBUG_INFO("No statuses to set.");
    }
#endif

    clearFileStatuses();

    QModelIndex index;

    foreach (int key, statuses.keys()) {
        m_fileStatuses.insert(key, statuses[key]);
        index = createIndex(key, 0);
        emit dataChanged(index, index);
    }
}


/*!
  Returns status of the file with \a index or FileModel::None if not found.
*/
FileModel::Status FileModel::fileStatus(int index) const
{
    if (index >= 0 && index < m_files.count() &&
        m_fileStatuses.contains(index)) {
        return m_fileStatuses[index];
    }

    return None;
}


/*!
  Clears the model content.
*/
void FileModel::clear()
{
    DEBUG_INFO("Will remove" << m_files.count() << "items.");

    while (!m_files.empty()) {
        removeRow(m_files.count() - 1, QModelIndex());
    }
}


/*!
  Clears the file statuses.
*/
void FileModel::clearFileStatuses()
{
    DEBUG_POINT;

    QModelIndex index;

    foreach (int key, m_fileStatuses.keys()) {
        m_fileStatuses.remove(key);
        index = createIndex(key, 0);
        emit dataChanged(index, index);
    }
}


// End of file.
